package com.uinnova.websocketstu.websocket;
import org.springframework.stereotype.Component;

import javax.servlet.annotation.WebListener;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;

/*
*@author 王刚
*@date 2019-02-01 10:01
*serverEndPoint 类层次的注解，将目前的类定义成一个websocket服务器端，值被用来监听
*/


@ServerEndpoint(value = "/websocket")
@Component
public class MyWebSocket {

    /*
    *静态变量，记录当前在线人数
    */
  private static int onlineCount = 0;
  /*
  *存放每个客户端对应的myWebSocket对象
  */
  private static CopyOnWriteArrayList<MyWebSocket>  webSocketSet = new CopyOnWriteArrayList<MyWebSocket>();


 /*
 *与每个客户端会话，需要它来发送数据
 */
  private Session session;

  /*
  *建立连接成功的调用方法
  */

  @OnOpen
    public void onOpen(Session session){
      this.session = session;
      webSocketSet.add(this);
      addOnlineCount();
      System.out.println("有新连接加入！当前在线人数为"+getOnlineCount());
      try {
          sendMessage("有新连接加入，当前在线人数为："+getOnlineCount());
      } catch (IOException e) {
          System.out.println("IO异常");
      }
  }

//

  /*
  *连接关闭的方法
  */
  @OnClose
  public void onClose(){
      webSocketSet.remove(this);
      subOnlineCount();
      System.out.println("有一连接关闭,当前在线人数为"+getOnlineCount());

  }


  /*
  *收到客户端消息后调用的方法
  */
  @OnMessage
  public void onMessage(String message,Session session){
      System.out.println("来自客户端的消息"+message);
      for(MyWebSocket item: webSocketSet){
          try {
              item.sendMessage(message);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  }


  /*
  *发生错误时
  *try语句出错的时候会执行catch中的消息，实例化exception，printStackTrace：在控制台打印错误的位置及信息
  */
  @OnError
  public void onError(Session session,Throwable error){
      System.out.println("发生错误");
      error.printStackTrace();
  }


/*
*群发自定义消息
*/
public static void sendInfo(String message) throws IOException{
    for(MyWebSocket item: webSocketSet){
        try{
            item.sendMessage(message);
        } catch (IOException e){
            continue;
        }
    }
}


  /*
  *websocket的session发送消息
  * getAsyncRemote发送消息是异步的，用的比较多，getBasicRemote发送消息是同步的，用的少，（能用来发送部分消息）
  */
  public void sendMessage(String message) throws IOException{
      this.session.getAsyncRemote().sendText(message);
  }


    /*
    *增加在线人数
    */

  public static synchronized void addOnlineCount(){
      MyWebSocket.onlineCount++;
  }


    public static synchronized void subOnlineCount(){
      MyWebSocket.onlineCount--;
    }

  public static synchronized int getOnlineCount(){
      return onlineCount;
  }

}



/*
*@author 王刚
*@data  2019-02-17 15:51
*总结：websocket 服务端的步骤
*
* 1.建立连接的方法 onopen（session）
* 2.连接出错  onerror(Session session,Throwable error）
* 3.关闭连接  onclose()
* 4.发送消息 onmessage(String message,Session session)
*/
